﻿using System.Collections.Generic;
using System.Drawing;
using System.IO;

namespace ShpViewer
{
    public class ShapeFileForView
    {
        private string fileName;
        private Header header;
        private float lastOffsetX = 0;
        private float lastOffsetY = 0;
        private float lastScaleX = 1;
        private float lastScaleY = 1;
        private float zoomX;
        private float zoomY;
        private List<MyPoint> points;
        private List<Line> lines;
        private List<Polygon> polygons;

        public ShapeFileForView(string shapeFile)
        {
            polygons = new List<Polygon>();
            points = new List<MyPoint>();
            lines = new List<Line>();
            header = new Header();
            fileName = shapeFile;
        }

        public void Read()
        {
            FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            ExtendBinaryReader extendBinaryReader = new ExtendBinaryReader(fileStream);
            header.Read(extendBinaryReader);
            while (extendBinaryReader.BaseStream.Position < extendBinaryReader.BaseStream.Length)
            {
                if (header.shapeType == 1)
                {
                    MyPoint point = new MyPoint();
                    point.Read(extendBinaryReader);
                    points.Add(point);
                }
                if (header.shapeType == 3)
                {
                    Line line = new Line();
                    line.Read(extendBinaryReader);
                    lines.Add(line);
                }
                if (header.shapeType == 5)
                {
                    Polygon polygon = new Polygon();
                    polygon.Read(extendBinaryReader);
                    polygons.Add(polygon);
                }
            }
            extendBinaryReader.Close();
        }

        /// <summary>
        /// Render for scale change.
        /// </summary>
        /// <param name="width">image width</param>
        /// <param name="height">image height</param>
        /// <param name="scaleX">x zoom scale</param>
        /// <param name="scaleY">y zoom scale</param>
        /// <param name="centerX">x of center point </param>
        /// <param name="centerY">y of center point </param>
        /// <returns></returns>
        public Image Render(int width, int height,float scaleX, float scaleY, int centerX, int centerY)
        {
            float oldX = (centerX - lastOffsetX) / lastScaleX;
            lastOffsetX = centerX - oldX * scaleX;
            float oldY = (centerY - lastOffsetY) / lastScaleY;
            lastOffsetY = centerY - oldY * scaleY;

            // Shape enlarge times;
            lastScaleX = scaleX;
            lastScaleY = scaleY;
            float zoomSuitX = (float)(width / (header.boundingBox.xMax - header.boundingBox.xMin));
            float zoomSuitY = (float)(height / (header.boundingBox.yMin - header.boundingBox.yMax));
            zoomX = zoomSuitX * scaleX;
            zoomY = zoomSuitY * scaleY;

            return Rending(width, height);
        }

        /// <summary>
        /// Render for Drag.
        /// </summary>
        /// <param name="width">image width</param>
        /// <param name="height">image height</param>
        /// <param name="offsetX">drag distance on x</param>
        /// <param name="offsetY">drag distance on y</param>
        /// <returns></returns>
        public Image Render(int width, int height, float offsetX, float offsetY)
        {
            lastOffsetX = lastOffsetX - offsetX;
            lastOffsetY = lastOffsetY - offsetY;

            return Rending(width,height);           
        }

        private Image Rending(int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage((Image)bmp);
            g.TranslateTransform(lastOffsetX, lastOffsetY);
            if (header.shapeType == 1)
            {
                for (int i = 0; i < points.Count; i++)
                {
                    points[i].Render(g, header.boundingBox.xMin, header.boundingBox.yMax, zoomX, zoomY);
                }
            }
            if (header.shapeType == 3)
            {
                for (int i = 0; i < lines.Count; i++)
                {
                    lines[i].Render(g, header.boundingBox.xMin, header.boundingBox.yMax, zoomX, zoomY);
                }
            }
            if (header.shapeType == 5)
            {
                for (int i = 0; i < polygons.Count; i++)
                {
                    polygons[i].Render(g, header.boundingBox.xMin, header.boundingBox.yMax, zoomX, zoomY);
                }
            }
            g.Dispose();
            return (Image)bmp;
        }
    }
}